package battleship.cxbr;

import java.util.Iterator;

import battleship.emss.Context;
import battleship.emss.CxBRAgent;
import battleship.emss.Fire;
import battleship.emss.Message;
import battleship.emss.Move;
import battleship.emss.Status;
import battleship.emss.physics;

public class KillContext extends Context {
	
	private double direction = 0;
	boolean fire = false;
	double lastX = 1;
	double lastY = 1;
	double lastTime = 1;
	double enemyDistance = 0;
	double deadReckoningDirection = 0;
	double myLastX = 0, myLastY = 0;
	double lastSpeed = 0;
	double deadTorpedo = 0;
	double preyDistance = 30000;
	boolean torpedoAlive = false;
	double speed = 6.0;
	int x = 0, y = 0, z = 0;
	double FIRE_THRESHOLD = 25000.0;
	final double STALK_THRESHOLD = 30000.0;
	double lastSeen = 0.0;
	boolean done = false;
	private int torpedoCount = 0;
	
	
	public KillContext(String n, CxBRAgent a) {
		super(n, a);
	}

	public void Initialize(double time) {
		torpedoCount = Agent.status.torpedos;
		System.out.println(torpedoCount);
	}

	@Override
	public void Action(double time) {
		FIRE_THRESHOLD = 25000 - ((torpedoCount - Agent.status.torpedos) * 1000);
		if (FIRE_THRESHOLD < 5000){
			FIRE_THRESHOLD = 5000;
		}
		Agent.status.status = Name;
		Agent.actions.clear();
		
		boolean found = false;
		boolean action = false;
		for(int i=0; i< Agent.detectedStatus.size(); i++){
			
			Status tmpStatus = Agent.detectedStatus.get(i);
			
			if( tmpStatus.team!=Agent.status.team && 
				tmpStatus.alive == 1){ // There is a living enemy that we see
				enemyDistance = Math.sqrt(	Math.pow(Agent.status.mx-tmpStatus.mx,2)+
											Math.pow(Agent.status.my-tmpStatus.my,2));
				
				/*if (tmpStatus.type == Agent.TORPEDO){
					action = true;
					if (enemyDistance < 25000){
						Agent.actions.clear();
						Agent.status.status = " Can't touch this!";
						direction = Math.atan2((tmpStatus.my - Agent.status.my),(tmpStatus.mx - Agent.status.mx)); // Run!
						Agent.actions.add(new Move(direction + Math.PI/2, 12));
						break;
					}
				} else */
				if (tmpStatus.type == Agent.SUB){
					lastSeen = time;
					action = true;
					preyDistance = enemyDistance;
					speed = 1 + (7 * preyDistance / FIRE_THRESHOLD); // Equilibrium at Xkm behind enemy sub - Optimal engagement
					speed = Math.min(speed, 20);
					direction = Math.atan2((tmpStatus.my - Agent.status.my),(tmpStatus.mx - Agent.status.mx));
					if (enemyDistance < FIRE_THRESHOLD){
						
						if (Agent.status.torpedos == 0){
							//speed = 1; // Ramming speed! (Doesn't work??)
							Agent.status.status = " Hammer time!";
						} else {
							double heading = tmpStatus.h;
							double leadingMeters = enemyDistance * (tmpStatus.v) / 10;
							//System.out.println("M:" + leadingMeters);
							Agent.actions.add(new Fire(Agent.status.mx,Agent.status.my,
									tmpStatus.mx + leadingMeters * Math.cos(heading),
									tmpStatus.my + leadingMeters * Math.sin(heading), 
									tmpStatus.name));
							//direction = direction + Math.PI;
						}
					}
					Agent.status.status += " Distance: " + (int) enemyDistance;
					Agent.actions.add(new Move(Agent.status.mx,Agent.status.my,tmpStatus.mx,tmpStatus.my, speed));
					
				}
			}
		}
		if (!action){ // Nothing sensed, follow old path
			Agent.status.status += " Distance: " + (int) preyDistance;
			Agent.actions.add(new Move(direction, speed));
		}
	}

	@Override
	public double ParentRule(double time) {
		//if (x++ % 1000 == 0)
			//System.out.println("Attack Parent Rule");
		/*if (Agent.incomingMessages.size() > 0){
			Iterator<Message> incMsgIter = Agent.incomingMessages.iterator();
			while (incMsgIter.hasNext()){
				System.out.println(incMsgIter.next().message);
			}
			Agent.incomingMessages.clear();
		}*/
		for(int i=0;i<Agent.detectedStatus.size();i++)
		{
			Status tmpStatus=Agent.detectedStatus.get(i);
			
			if(tmpStatus.team != Agent.status.team && 
					tmpStatus.type == Agent.SUB &&
					tmpStatus.alive == 1){
				lastSeen = time;
				direction = Math.atan2((tmpStatus.my - Agent.status.my),(tmpStatus.mx - Agent.status.mx));
				lastX = tmpStatus.mx;
				lastY = tmpStatus.my;
				lastTime = physics.SimTime;
				if (Evaluate.WAR){
					if (!done){
						done = true;
						System.out.println("WAR");
					}
					return 1.0d;
				}
			}
		}
		return 0.0d;
	}

	@Override
	public double SiblingRule(double time) {
		//if (y++ % 1000 == 0)
		//System.out.println("Attack Subling Rule");
		boolean torpedo = false;
		boolean sub = false;
		
		for(int i = 0; i < Agent.detectedStatus.size() ; i++){
			
			Status tmpStatus=Agent.detectedStatus.get(i);
			//System.out.println("Team: " + Agent.status.team);
			//Agent.status.

			if(	tmpStatus.team != Agent.status.team && 
				tmpStatus.alive == 1){
				if(	tmpStatus.type == Agent.SUB){
					lastSeen = time;
					sub = true;
					direction = Math.atan2((tmpStatus.my - Agent.status.my),(tmpStatus.mx - Agent.status.mx));				
					lastX = tmpStatus.mx;
					lastY = tmpStatus.my;
					lastTime = time;
					if (Evaluate.WAR){
						if (!done){
							done = true;
							System.out.println("WAR");
						}
						return 1.0d;
					}
				} else if (tmpStatus.type == Agent.TORPEDO){
					torpedo = true;
					break;
				}
			}
		}
		if (torpedo){
			return 0.0d;
		}
		else if (sub){ 
			return 1.0d; 
		}
		else {
			return 0.0d;
		}
	}

}
